﻿using SuperMap.Data;
using SuperMap.Realspace;
using System;
using System.Collections.Generic;
using System.Data;

namespace Ycjw.PipeLine.Map.Basic.SuperMap
{
    /// <summary>
    /// DatasetVector查询对象
    /// </summary>
    public class DatasetVectorEx
    {
        public static DatasetVector DatasetVectorByLayerName(Scene scene, string lyrName)
        {
            foreach (Layer3D lyr in scene.Layers)
            {
                if (lyr.Type == Layer3DType.Dataset)
                {
                    if (!(lyr is Layer3DDataset)) continue;
                    var dataset = (lyr as Layer3DDataset).Dataset;
                    if (!(dataset is DatasetVector)) continue;
                    var name = lyr.Name;
                    if (name != lyrName)
                        return dataset as DatasetVector;
                }
            }
            return null;
        }
        private readonly string layerName;
        public DatasetVectorEx(string lyrName)
        {
            layerName = lyrName;
        }
        private DatasetVector m_DatasetVector;

        public DatasetVector DatasetVector { get => m_DatasetVector; set => m_DatasetVector = value; }
        public List<string> ResultFields { get => resultFields; set => resultFields = value; }
        public List<string> OrderBy { get => orderBy; set => orderBy = value; }
        private bool m_HasGeometry = true;
        public bool HasGeometry
        {
            get { return m_HasGeometry; }
            set { m_HasGeometry = value; }
        }
        private List<string> resultFields = new List<string>();
        private List<string> orderBy = new List<string>();

        public double GetMinValue(string fieldName)
        {
            var val = MinMaxValue(fieldName, -1);
            if (val == null) return double.NaN;
            else return double.Parse(val.ToString());
        }

        public bool HasNullVal(string fieldName)
        {
            resultFields.Add(fieldName);
            m_HasGeometry = false;
            var dt = this.Query(fieldName + " is null");
            if (dt.Rows.Count > 0) return true;
            return false;
        }

        public Dictionary<string, double> UniqueValLength(string fieldName)
        {
            Dictionary<string, double> result = new Dictionary<string, double>();
            resultFields.Add(fieldName);
            m_HasGeometry = true;
            Recordset recordset = QueryToRecordset("1=1");
            try
            {
                // 查询得到结果记录集
                recordset.MoveFirst();
                Int32 length = recordset.RecordCount;
                for (int i = 0; i < length; i++)
                {
                    var val = recordset.GetString(fieldName);
                    if (string.IsNullOrEmpty(val)) val = "未知";
                    double leng = Geometrist.ComputeLength(recordset.GetGeometry() as GeoLine3D, new PrjCoordSys(4326));
                    if (!result.ContainsKey(val))
                    {
                        result.Add(val, leng);
                    }
                    else
                    {
                        result[val] += leng;
                    }
                    recordset.MoveNext();
                }

            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.Message);
            }
            finally
            {
                // 释放记录集
                //Dispose the recordset.
                if (recordset != null)
                    recordset.Dispose();
            }
            return result;
        }
        //返回行数
        public Dictionary<string, double> UniqueValLengths(string fieldName)
        {
            Dictionary<string, double> result = new Dictionary<string, double>();
            resultFields.Add(fieldName);
            m_HasGeometry = true;
            Recordset recordset = QueryToRecordset("1=1");
            try
            {
                // 查询得到结果记录集
                recordset.MoveFirst();
                Int32 length = recordset.RecordCount;
                for (int i = 0; i < length; i++)
                {
                    var val = recordset.GetString(fieldName);
                    if (string.IsNullOrEmpty(val)) val = "未知";
                    //  double leng = Geometrist.ComputeLength(recordset.GetGeometry() as GeoLine3D, new PrjCoordSys(4326));
                    if (!result.ContainsKey(val))
                    {
                        result.Add(val, 1);
                    }
                    else
                    {
                        result[val] += 1;
                    }
                    recordset.MoveNext();
                }

            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.Message);
            }
            finally
            {
                // 释放记录集
                //Dispose the recordset.
                if (recordset != null)
                    recordset.Dispose();
            }
            return result;
        }
        public int NullValCount(string fieldName)
        {
            resultFields.Add(fieldName);
            m_HasGeometry = false;
            var dt = this.Query(fieldName + " is null");
            return dt.Rows.Count;
        }
        public double StaticsticsLengthByMinMax(string fieldName, double min, double max, bool contaiinMax = true, object spatialQueryObject = null)
        {
            resultFields.Add(fieldName);
            m_HasGeometry = true;
            var lengthResult = 0.0d;
            string sqlWhere = fieldName + " >= " + min + " and " + fieldName + " <= " + max;
            if (!contaiinMax) sqlWhere = fieldName + " >= " + min + " and " + fieldName + " < " + max;

            Recordset recordset = QueryToRecordset(sqlWhere, spatialQueryObject);
            try
            {
                // 查询得到结果记录集
                recordset.MoveFirst();
                Int32 length = recordset.RecordCount;
                for (int i = 0; i < length; i++)
                {
                    lengthResult += Geometrist.ComputeLength(recordset.GetGeometry() as GeoLine3D, new PrjCoordSys(4326));
                    recordset.MoveNext();
                }

            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.Message);
            }
            finally
            {
                // 释放记录集
                //Dispose the recordset.
                if (recordset != null)
                    recordset.Dispose();
            }

            return lengthResult;
        }
        public double GetMaxValue(string fieldName)
        {
            var val = MinMaxValue(fieldName, 1);
            if (val == null) return double.NaN;
            else return double.Parse(val.ToString());
        }
        public double[] GetMinMaxValue(string fieldName)
        {
            var val = MinMaxValue(fieldName, 0);
            if (val == null) return new double[] { };
            else return (double[])val;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fieldName"></param>
        /// <param name="min">min = 0,获取最小值，最大值；-1时获取最小值，1时获取最大值</param>
        /// <returns></returns>
        private object MinMaxValue(string fieldName, int minMax = 0)
        {
            this.m_HasGeometry = false;
            resultFields.Add(fieldName);
            if (minMax == 1)
                orderBy.Add(fieldName + " desc");
            else
                orderBy.Add(fieldName + " asc");
            var dt = this.Query(fieldName + " is not null");
            if (dt.Rows.Count > 0)
            {
                if (minMax != 0)
                    return double.Parse(dt.Rows[0][0].ToString());
                else
                {
                    return new double[]
                    {
                        double.Parse(dt.Rows[0][0].ToString()),
                        double.Parse(dt.Rows[dt.Rows.Count-1][0].ToString())
                    };
                }
            }
            return null;
        }

        public int GetCount(string sqlWhere, object spatialQueryObject = null)
        {
            // 构造查询参数类，设置查询条件
            // Initialize the query parameter class

            QueryParameter queryParameter = new QueryParameter
            {
                AttributeFilter = sqlWhere,
                ResultFields = resultFields?.ToArray(),
                CursorType = CursorType.Static,
                HasGeometry = false
            };

            if (spatialQueryObject != null)
            {
                queryParameter.SpatialQueryObject = spatialQueryObject;
                queryParameter.SpatialQueryMode = SpatialQueryMode.Intersect;
            }

            Recordset recordset = null;
            try
            {
                // 查询得到结果记录集
                recordset = m_DatasetVector.Query(queryParameter);
                return recordset.RecordCount;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Commons.LogHelper.Error(ex.Message);
            }
            finally
            {
                // 释放记录集
                //Dispose the recordset.
                if (recordset != null)
                    recordset.Dispose();
            }
            return -1;
        }
        public Recordset QueryToRecordset(string sqlWhere, object spatialQueryObject = null)
        {

            // 构造查询参数类，设置查询条件
            // Initialize the query parameter class

            QueryParameter queryParameter = new QueryParameter
            {
                AttributeFilter = sqlWhere,
                ResultFields = resultFields?.ToArray(),
                OrderBy = orderBy?.ToArray(),
                CursorType = CursorType.Static,
                HasGeometry = this.m_HasGeometry
            };
            if (spatialQueryObject != null)
            {
                queryParameter.SpatialQueryObject = spatialQueryObject;
                queryParameter.SpatialQueryMode = SpatialQueryMode.Intersect;
            }

            try
            {
                // 查询得到结果记录集
                Recordset recordset = m_DatasetVector.Query(queryParameter);
                // 输出记录集记录
                //Get the result dataset.
                return recordset;

            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.Message);
            }
            return null;
        }
        public DataTable Query(string sqlWhere, object spatialQueryObject = null)
        {
            // 构造查询参数类，设置查询条件
            // Initialize the query parameter class

            QueryParameter queryParameter = new QueryParameter
            {
                AttributeFilter = sqlWhere,
                ResultFields = resultFields?.ToArray(),
                OrderBy = orderBy?.ToArray(),
                CursorType = CursorType.Static,
                HasGeometry = this.m_HasGeometry
            };
            if (spatialQueryObject != null)
            {
                queryParameter.SpatialQueryObject = spatialQueryObject;
                queryParameter.SpatialQueryMode = SpatialQueryMode.Intersect;
            }

            Recordset recordset = null;
            try
            {
                // 查询得到结果记录集
                recordset = m_DatasetVector.Query(queryParameter);

                // 输出记录集记录
                //Get the result dataset.
                return ToDataTable(recordset);

            }
            catch (Exception ex)
            {

                Console.WriteLine(ex.Message);
            }
            finally
            {
                // 释放记录集
                //Dispose the recordset.
                if (recordset != null)
                    recordset.Dispose();
            }
            return null;
        }
        public DataTable ToDataTable(Recordset recordset)
        {
            DataTable dt = new DataTable(layerName);
            try
            {
                FieldInfos fieldInfos = recordset.GetFieldInfos();
                // 输出字段名
                // Output the field name
                Int32 count = fieldInfos.Count;
                for (Int32 i = 0; i < count; i++)
                {
                    String fieldname = fieldInfos[i].Name;
                    if (ResultFields != null && resultFields.Count > 0)
                    {
                        if (ResultFields.Contains(fieldname))
                            dt.Columns.Add(fieldname);
                    }
                    else
                    {
                        dt.Columns.Add(fieldname);
                    }
                }
                // 输出字段值
                // Output the field value
                recordset.MoveFirst();
                Int32 length = recordset.RecordCount;
                for (int i = 0; i < length; i++)
                {
                    DataRow dr = dt.NewRow();
                    var actIndex = 0;
                    for (Int32 j = 0; j < count; j++)
                    {
                        if (ResultFields != null && resultFields.Count > 0)
                        {
                            if (ResultFields.Contains(fieldInfos[j].Name))
                            {
                                var objValue = recordset.GetFieldValue(j);
                                String value = objValue?.ToString();
                                dr[actIndex++] = value;
                            }
                        }
                        else
                        {
                            var objValue = recordset.GetFieldValue(j);
                            string value = objValue?.ToString();
                            dr[actIndex++] = value;
                        }
                    }
                    dt.Rows.Add(dr);
                    Console.WriteLine();
                    recordset.MoveNext();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return dt;
        }
    }
}
